﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Configuration;
using System.Threading;

namespace Spider
{
    public class Rules
    {
        #region Field
        private string mTitleRegex;
        private string mDescriptionRegex;
        private string mUrlPrefix;
        private string mImageUrlRegex;
        private string mPriceRegex;
        private string mName;
        private string mProductUrlFilter;
        private string mCharset;
        private static Dictionary<string, Rules> mDicRules = new Dictionary<string, Rules>();
        private static Rules mRule;
        private int mStatus;
        #endregion

        #region Properties
        public static Rules Instance
        {
            get
            {
                if (mRule == null)
                {
                    mRule = new Rules();
                    LoadRules();
                }
                return mRule;
            }
        }

        public static void Reset()
        {
            mDicRules.Clear();
            mRule = null;
        }

        public Dictionary<string, Rules> DicRules
        {
            get {
                //Monitor.Enter(mDicRules);
                return mDicRules;
                //Monitor.Pulse(mDicRules);
                //Monitor.Exit(mDicRules);
            }
        }

        public string TitleRegex
        {
            get { return mTitleRegex; }
            set { mTitleRegex = value; }
        }

        public string DescriptionRegex
        {
            get { return mDescriptionRegex; }
            set { mDescriptionRegex = value; }
        }

        public string UrlPrefix
        {
            get { return mUrlPrefix; }
            set { mUrlPrefix = value; }
        }

        public string ImageUrlRegex
        {
            get { return mImageUrlRegex; }
            set { mImageUrlRegex = value; }
        }

        public string PriceRegex
        {
            get { return mPriceRegex; }
            set { mPriceRegex = value; }
        }

        public string Name
        {
            get { return mName; }
            set { mName = value; }
        }

        public string ProductUrlFilter
        {
            get { return mProductUrlFilter; }
            set { mProductUrlFilter = value; }
        }
        public string Charset
        {
            get { return mCharset; }
            set { mCharset = value; }
        }

        public int Status
        {
            get { return mStatus; }
            set { mStatus = value; }
        }
        #endregion

        #region Method

        public bool Contain(Rules rule)
        {
            bool blResult = false;

            foreach (Rules s in mDicRules.Values)
            {
                if (rule.Name == s.Name)
                {
                    blResult = true;
                    break;
                }

                if (rule.TitleRegex == s.TitleRegex &&
                    rule.DescriptionRegex == s.DescriptionRegex &&
                    rule.ImageUrlRegex == s.ImageUrlRegex &&
                    rule.PriceRegex == s.PriceRegex &&
                    rule.ProductUrlFilter==s.ProductUrlFilter &&
                    rule.Charset==s.Charset)
                {
                    blResult = true;
                    break;
                }
            }

            return blResult;
        }
        public Rules Find(string Name)
        {
            Rules rule = null;

            foreach (string key in mDicRules.Keys)
            {
                rule = mDicRules[key];

                if(rule.Name==Name)
                {
                    return rule;
                }
            }
            return null;
        }

        private void RemoveRule(string Name)
        {
            Rules rule = null;

            foreach (string key in mDicRules.Keys)
            {
                rule = mDicRules[key];

                if (rule.Name == Name)
                {
                    mDicRules.Remove(key);
                    break;
                }
            }
        }

        private string Parse(string regex)
        {
            return regex;
        }

        private void AddRule(Rules set)
        {
            AddRule(set.Name, set.TitleRegex, set.mDescriptionRegex, set.UrlPrefix, set.ImageUrlRegex, set.PriceRegex, set.ProductUrlFilter, set.Charset);
        }

        private void AddRule(string MName, string MTitleRegex, string MDescriptRegex, string MUrlPrefix, string MImageUrlRegex, string MPriceRegex, string MProductUrlFilter, string MCharset)
        {
            Rules rule = new Rules();
            rule.Name = MName;
            rule.TitleRegex = Parse(MTitleRegex);
            rule.DescriptionRegex = Parse(MDescriptRegex);
            rule.UrlPrefix = MUrlPrefix;
            rule.ImageUrlRegex = Parse(MImageUrlRegex);
            rule.PriceRegex = Parse(MPriceRegex);
            rule.ProductUrlFilter = Parse(MProductUrlFilter);
            rule.Charset = Parse(MCharset);
            rule.Status =Convert.ToInt32(Spider.Status.STATUS_UNQUEUEDING);

            if (!Contain(rule))
            {
                mDicRules.Add(MName, rule);
            }
        }

        public Rules GetSettings(string MName)
        {
            if (mDicRules.ContainsKey(MName))
                return mDicRules[MName];
            else
                return null;
        }

        public void Clear()
        {
            mDicRules.Clear();
        }

        private static void LoadRules()
        {
            XmlDocument doc = new XmlDocument();
            string filename = Spider.Properties.Settings.Default.RulesFileName;
            doc.Load(filename);

            Rules rule = null;

            XmlNodeList rules = doc.SelectNodes("Rules/Rule");

            foreach (XmlNode mrule in rules)
            {
                rule = new Rules();
                rule.Name = mrule.Attributes["Name"].Value.Trim();
                rule.UrlPrefix = mrule.Attributes["UrlPrefix"].Value.Trim();
                rule.ProductUrlFilter = mrule.Attributes["ProductUrlFilter"].Value.Trim();
                rule.Charset = mrule.Attributes["Charset"].Value.Trim();
                rule.Status = Convert.ToInt16(mrule.Attributes["Status"].Value.Trim());
                rule.TitleRegex = mrule.SelectSingleNode("TitleRegex").InnerText.Trim();
                rule.DescriptionRegex = mrule.SelectSingleNode("DescriptionRegex").InnerText.Trim();
                rule.ImageUrlRegex = mrule.SelectSingleNode("ImageUrlRegex").InnerText.Trim();
                rule.PriceRegex = mrule.SelectSingleNode("PriceRegex").InnerText.Trim();

                mDicRules.Add(rule.UrlPrefix, rule);
            }
        }

        public void AddRuleToXML(Rules MRule)
        {
            XmlDocument doc = new XmlDocument();
            string filename = Spider.Properties.Settings.Default.RulesFileName;
            doc.Load(filename);

            if(!Contain(MRule))
            {
                XmlNode root=doc.SelectSingleNode("Rules");

                XmlNode rule = doc.CreateElement("Rule");

                XmlAttribute atr = doc.CreateAttribute("UrlPrefix");
                atr.Value = MRule.UrlPrefix;
                rule.Attributes.Append(atr);

                atr = doc.CreateAttribute("Name");
                atr.Value = MRule.UrlPrefix;
                rule.Attributes.Append(atr);

                atr = doc.CreateAttribute("ProductUrlFilter");
                atr.Value = MRule.ProductUrlFilter;
                rule.Attributes.Append(atr);

                atr = doc.CreateAttribute("Charset");
                atr.Value = MRule.Charset;
                rule.Attributes.Append(atr);

                atr = doc.CreateAttribute("Status");
                atr.Value = Convert.ToInt16(Spider.Status.STATUS_UNQUEUEDING).ToString();
                rule.Attributes.Append(atr);

                XmlNode node = doc.CreateElement("TitleRegex");
                node.InnerText = MRule.TitleRegex;
                rule.AppendChild(node);

                node = doc.CreateElement("DescriptionRegex");
                node.InnerText = MRule.DescriptionRegex;
                rule.AppendChild(node);

                node = doc.CreateElement("ImageUrlRegex");
                node.InnerText = MRule.ImageUrlRegex;
                rule.AppendChild(node);

                node = doc.CreateElement("PriceRegex");
                node.InnerText = MRule.PriceRegex;
                rule.AppendChild(node);

                root.AppendChild(rule);
            }

            AddRule(MRule);

            doc.Save(filename);
        }

        public void DeleteRuleFromXML(string Name)
        {
            XmlDocument doc = new XmlDocument();
            string filename = Spider.Properties.Settings.Default.RulesFileName;
            doc.Load(filename);

            XmlNode rule = doc.SelectSingleNode(string.Format("Rules/Rule[@Name='{0}']",Name));
            XmlNode root = doc.SelectSingleNode("Rules");

            root.RemoveChild(rule);

            RemoveRule(Name);

            doc.Save(filename);
        }

        public void ModifyRuleToXML(Rules MRule)
        {
            XmlDocument doc = new XmlDocument();
            string filename = Spider.Properties.Settings.Default.RulesFileName;
            doc.Load(filename);

            if (Contain(MRule))
            {
                XmlNode rule = doc.SelectSingleNode(string.Format(@"Rules/Rule[@Name='{0}']",MRule.Name));

                XmlAttribute atr =rule.Attributes["UrlPrefix"];
                atr.Value = MRule.UrlPrefix;

                atr = rule.Attributes["Name"];
                atr.Value = MRule.Name;

                atr = rule.Attributes["ProductUrlFilter"];
                atr.Value = MRule.ProductUrlFilter;

                atr = rule.Attributes["Charset"];
                atr.Value = MRule.Charset;

                atr = rule.Attributes["Status"];
                atr.Value = MRule.Status.ToString();

                XmlNode node = rule.SelectSingleNode(@"TitleRegex");
                node.InnerText = MRule.TitleRegex;

                node = rule.SelectSingleNode(@"DescriptionRegex");
                node.InnerText = MRule.DescriptionRegex;

                node = rule.SelectSingleNode(@"ImageUrlRegex");
                node.InnerText = MRule.ImageUrlRegex;

                node = rule.SelectSingleNode(@"PriceRegex");
                node.InnerText = MRule.PriceRegex;
            }

            doc.Save(filename);

            Clear();
            LoadRules();
        }

        public void ModifyRuleToXMLNotReload(Rules MRule)
        {
            XmlDocument doc = new XmlDocument();
            string filename = Spider.Properties.Settings.Default.RulesFileName;
            doc.Load(filename);

            if (Contain(MRule))
            {
                XmlNode rule = doc.SelectSingleNode(string.Format(@"Rules/Rule[@Name='{0}']", MRule.Name));

                XmlAttribute atr = rule.Attributes["UrlPrefix"];
                atr.Value = MRule.UrlPrefix;

                atr = rule.Attributes["Name"];
                atr.Value = MRule.Name;

                atr = rule.Attributes["ProductUrlFilter"];
                atr.Value = MRule.ProductUrlFilter;

                atr = rule.Attributes["Charset"];
                atr.Value = MRule.Charset;

                atr = rule.Attributes["Status"];
                atr.Value = MRule.Status.ToString();

                XmlNode node = rule.SelectSingleNode(@"TitleRegex");
                node.InnerText = MRule.TitleRegex;

                node = rule.SelectSingleNode(@"DescriptionRegex");
                node.InnerText = MRule.DescriptionRegex;

                node = rule.SelectSingleNode(@"ImageUrlRegex");
                node.InnerText = MRule.ImageUrlRegex;

                node = rule.SelectSingleNode(@"PriceRegex");
                node.InnerText = MRule.PriceRegex;
            }

            doc.Save(filename);
        }
        #endregion
    }
}
